<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="renderer" content="webkit|ie-comp|ie-stand">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
  <meta http-equiv="Cache-Control" content="no-siteapp" />
  <title>考勤月度汇总</title>
</head>

<body>
  <div id="app" v-loading.fullscreen.lock="loading">
    <div class="month-summary">
      <div>
        <search-btn-view btn-text="汇总查询" :before-search="checkSearchValid" @before-open="resetSearch" @search="searchData">
          <template slot="append">
            <el-button size="medium" type="primary" @click="exportExcel">导出excel</el-button>
            <span v-if="sumSalary!==null" style="margin-left:10px">
              实发总工资:{{sumSalary}}
            </span>
          </template>
          <div slot="search-content">
            <search-form :search="search" :person-list="personList"></search-form>
          </div>
        </search-btn-view>
      </div>
      <div class="month-summary-table-div" :class="{'hasPage':pagination.totalCount!==0}">
        <el-table fit stripe border class="month-summary-table" :data="attendanceList" style="width: 100%" height="parent">
          <el-table-column :resizable="false" label="姓名" prop="userName" key="userName" min-width="100px" align="center" fixed="left">
          </el-table-column>
          <el-table-column :resizable="false" label="部门" prop="deptName" key="deptName" min-width="80px" align="center"></el-table-column>
          <el-table-column :resizable="false" label="车间" prop="workshopName" key="workshopName" min-width="80px" align="center"></el-table-column>
          <el-table-column :resizable="false" label="编号" prop="userId" key="userId" min-width="60px" align="center"></el-table-column>
          <el-table-column :resizable="false" label="工号" prop="workerNo" key="workerNo" min-width="60px" align="center"></el-table-column>
          <el-table-column :resizable="false" label="早退时长" key="earlyDuration" min-width="110px" align="center">
            <template slot-scope="scope">
              {{SysUtil.getDurationStr(scope.row.earlyDuration)}}
            </template>
          </el-table-column>
          <el-table-column :resizable="false" label="迟到时长" key="lateDuration" min-width="110px" align="center">
            <template slot-scope="scope">
              {{SysUtil.getDurationStr(scope.row.lateDuration)}}
            </template>
          </el-table-column>
          <el-table-column :resizable="false" label="请假时长" key="leaveDuration" min-width="110px" align="center">
            <template slot-scope="scope">
              {{SysUtil.getDurationStr(scope.row.leaveDuration)}}
            </template>
          </el-table-column>
          <el-table-column :resizable="false" label="加班时长" key="workOvertimeDuration" min-width="110px" align="center">
            <template slot-scope="scope">
              {{SysUtil.getDurationStr(scope.row.workOvertimeDuration)}}
            </template>
          </el-table-column>
          <el-table-column :resizable="false" label="工作时长" key="workTimeDuration" min-width="110px" align="center">
            <template slot-scope="scope">
              {{SysUtil.getDurationStr(scope.row.workTimeDuration)}}
            </template>
          </el-table-column>
          <el-table-column :resizable="false" label="行政奖励" prop="administrativePenaltyForAward" key="administrativePenaltyForAward" min-width="110px"
            align="center">
          </el-table-column>
          <el-table-column :resizable="false" label="行政处罚" prop="administrativePenaltyForPunish" key="administrativePenaltyForPunish"
            min-width="110px" align="center">
          </el-table-column>
          <el-table-column :resizable="false" label="实发工资" key="realSalary" min-width="110px" align="center">
            <template slot-scope="scope">
              <div class="table-btns" @click="lookSalaryDetail(scope.row)">{{scope.row.realSalary}}</div>
            </template>
          </el-table-column>

          <template v-for="head in tableHead">
            <el-table-column :resizable="false" :label="head" :key="`date_${head}`" min-width="190px">
              <template slot="header" slot-scope="scope">
                <div class="tableHeader">{{moment(head).format('dd')}}</div>
                <div class="tableHeader" style="text-align:right;">{{moment(head).format('D')}}</div>
              </template>
              <template slot-scope="scope">
                <div class="attednanceInfo" v-html="scope.row.workdateObj[head]" @click="toAttendanceDetail(scope.row,head)"></div>
              </template>
            </el-table-column>
          </template>
        </el-table>
      </div>
      <table-pagination v-if="pagination.totalCount!==0" :pagination="pagination" @change="pageChange">
      </table-pagination>
    </div>

    <el-dialog :title="detailTitle" :visible.sync="openDetail" top="10vh" custom-class="attendanceDetailDialog" @closed="attendanceDetail=null"
      width="50%">
      <div style="height:calc(80vh - 54px);overflow:auto">
        <attendance-detail v-if="openDetail" :detail="attendanceDetail"></attendance-detail>
      </div>
    </el-dialog>

    <el-dialog fullscreen class="dialog-fullscreen" title="工资详情" :visible.sync="openSalaryDailog" @closed="selectAttendance=null">
      <div v-if="openSalaryDailog" style="height:100%;overflow:auto">
        <salary-detail :attendance="selectAttendance" :search="oldSearch"></salary-detail>
      </div>
    </el-dialog>
  </div>
</body>

<script src="../../myJs/importFile.js"></script>
<script>
  importFile([
    "/vueSystem/components/css/searchBtnView.css",
    "/vueSystem/components/css/deptTransfer.css",
    "../components/css/deptPersonSelect.css",
    "../components/css/attendanceSearchForm.css",
    "../components/css/attendanceDetail.css",
    "./css/salaryDetail.css"
  ], [
    "/vueSystem/i18n/index.js",
    "/vueSystem/components/searchBtnView.js",
    "/vueSystem/components/deptTransfer.js",
    "/vueSystem/mixins/tablePaginationMixin.js",
    "/vueSystem/mixins/datePickerOptionsMixin.js"
  ]);

</script>
<script src="../utils/moduleUtil.js"></script>
<script src="../components/deptPersonSelect.js"></script>
<script src="../components/attendanceSearchForm.js"></script>
<script src="../components/attendanceDetail.js"></script>
<script src="./salaryDetail.js"></script>
<script>
  var app = new Vue({
    el: '#app',
    mixins: [
      tablePaginationMixin()
    ],
    data: function () {
      var search = {
        startDate: moment().startOf('month').valueOf(),
        endDate: moment().valueOf(),
        deptPerson: {
          depts: [],
          persons: []
        }
      };

      return {
        loading: false,
        search: _.cloneDeep(search),
        oldSearch: _.cloneDeep(search),
        personList: [],
        attendanceList: [],
        tableHead: [],
        openDetail: false,
        detailTitle: '',
        attendanceDetail: null,
        openSalaryDailog: false,
        selectAttendance: null,
        SysUtil: SysUtil,
        sumSalary: null
      };
    },

    created: function () {
      this.loading = true;
      var self = this;
      Promise.all([
        this.setPersonList(),
        this.setAttendanceList(true, true)
      ]).then(function (res) {
        self.loading = false;
      }).catch(function () {
        self.loading = false;
      });
    },

    methods: {
      setPersonList: function () {
        var self = this;
        return ajaxRequest('dingTalk/askForApprover').then(function (personList) {
          personList = _.map(personList, function (person) {
            return {
              deptId: person.deptId,
              deptName: person.deptName,
              userId: person.id,
              userName: person.personName
            };
          });
          self.personList = personList;
          return personList;
        });
      },

      setAttendanceList: function (isSearch, hasSum) {
        if (!isSearch) {
          this.search = _.cloneDeep(this.oldSearch);
        }

        var postData = this.getPostData();

        var promiseList = [this.queryAttendanceSummary(postData)];
        if (hasSum) {
          promiseList.push(this.queryAttendanceState(postData));
        }

        var self = this;
        return Promise.all(promiseList).then(function (res) {
          if (isSearch) {
            self.oldSearch = _.cloneDeep(self.search);
          }
          return res;
        });
      },

      queryAttendanceSummary: function (postData) {
        postData = _.cloneDeep(postData);
        var pagination = this.pagination;
        var currentPage = pagination.currentPage;
        var pageSize = pagination.pageSize;
        var start = (currentPage - 1) * pageSize;
        postData.start = start;
        postData.length = pageSize;

        var self = this;
        return ajaxRequest('dingTalk/querySummaryBody', postData).then(function (res) {
          var attendanceList = res.returnData;
          self.formatAttendanceList(attendanceList);

          self.setTableHead(postData);
          self.attendanceList = attendanceList;
          self.pagination.totalCount = res.iTotalRecords;
          return attendanceList;
        });
      },

      queryAttendanceState: function (postData) {
        postData = _.cloneDeep(postData);
        var self = this;
        return ajaxRequest('dingTalk/querySummaryBody', postData).then(function (res) {
          var data = res.returnData;
          var sumSalary = _.sumBy(data, 'realSalary');
          sumSalary = _.round(sumSalary, 2);
          self.sumSalary = sumSalary;
          return sumSalary;
        });
      },

      getPostData: function () {
        var search = this.search;
        var postData = {
          startDate: moment(search.startDate).format('YYYY-MM-DD'),
          endDate: moment(search.endDate).format('YYYY-MM-DD'),
        };

        var deptPerson = search.deptPerson;
        postData.deptIds = JSON.stringify(_.map(deptPerson.depts, 'id'));
        postData.userIds = JSON.stringify(_.map(deptPerson.persons, 'id'));
        return postData;
      },

      formatAttendanceList: function (attendanceList) {
        var salaryFields = ['attendanceSalary', 'realSalary', 'socialSecurity', 'accumulationFund',
          'otherAddition', 'otherDeduction', 'pieceWage', 'electricFee', 'waterFee', 'applyRepairMoney'
        ];
        for (var i = 0; i < attendanceList.length; i++) {
          var attendance = attendanceList[i];

          for (var j = 0; j < salaryFields.length; j++) {
            var salaryField = salaryFields[j];
            var value = attendance[salaryField];
            if (typeof value === 'number') {
              value = _.round(value, 2);
              attendance[salaryField] = value;
            }
          }

          var realSalary = attendance.realSalary;
          var personalIncomeTax = SysUtil.getPersonalIncomeTax(realSalary);
          attendance.personalIncomeTax = personalIncomeTax;

          var socialSecurity = attendance.socialSecurity;
          var companySocialSecurity = socialSecurity * 18 / 8;
          companySocialSecurity = _.round(companySocialSecurity, 2);
          attendance.companySocialSecurity = companySocialSecurity;

          var leaveList = attendance.leaveList;
          leaveList = _.orderBy(leaveList, ['startTime'], ['asc']);

          var workdateList = attendance.workdateList;
          if (workdateList.length === 0) {
            continue;
          }

          var workdateObj = {};
          for (var j = 0; j < workdateList.length; j++) {
            var workdate = workdateList[j];
            var leaves = _.filter(leaveList, function (leave) {
              var startTime = leave.startTime;
              var endTime = leave.endTime;
              return moment(workdate.workdate).isBetween(startTime, endTime, 'day', '[]');
            });
            if (leaves.length > 0) {
              workdate.leaveList = leaves;
            }

            var showHtml = this.getAttendanceInfo(workdate);
            workdateObj[workdate.workdate] = showHtml;
          }

          attendance.workdateObj = workdateObj;
        }
      },

      setTableHead: function (postData) {
        var startDate = postData.startDate;
        var endDate = postData.endDate;
        var date = moment(startDate).valueOf();
        var tableHead = [];
        while (moment(date).isSameOrBefore(endDate, 'day')) {
          tableHead.push(moment(date).format('YYYY-MM-DD'));
          date = moment(date).add(1, 'day').valueOf();
        }
        this.tableHead = tableHead;
      },

      resetAttendanceList: function (isSearch, hasSum) {
        this.loading = true;
        var self = this;
        this.setAttendanceList(isSearch, hasSum).then(function () {
          self.loading = false;
        }).catch(function () {
          self.loading = false;
        });
      },

      checkSearchValid: function () {
        var search = this.search;
        var startDate = search.startDate;
        var endDate = search.endDate;
        if (moment(startDate).add(1, 'month').isBefore(endDate, 'day')) {
          this.$alert('只能查询一个月以内的汇总数据', '信息');
          return false;
        }
        return true;
      },

      resetSearch: function () {
        this.search = _.cloneDeep(this.oldSearch);
      },

      searchData: function () {
        this.pagination.currentPage = 1;
        this.resetAttendanceList(true, true);
      },

      pageChange: function () {
        this.resetAttendanceList();
      },

      getAttendanceInfo: function (workdate) {
        if (workdate === undefined) {
          return '';
        }
        var state = workdate.state;
        var text = workdate.text.trim();
        text = _.replace(text, /\n/g, '<br>');
        var leaveList = workdate.leaveList;
        var strArray = [];
        if (leaveList === undefined) {
          strArray.push(`<div class="state-${state}">${text}</div>`);
        } else {
          if (text !== '旷工') {
            strArray.push(`<div class="state-${state}">${text}</div>`);
          }
          for (var i = 0; i < leaveList.length; i++) {
            var leave = leaveList[i];
            var startTime = moment(leave.startTime).format('MM-DD HH:mm');
            var endTime = moment(leave.endTime).format('MM-DD HH:mm');
            var str =
              `<div class="state-0">
                ${i18n.getMsg('attendance.takeOffType.'+leave.type)} ${startTime}到${endTime}<br>
                共计${leave.duration}小时</div>
              `;
            strArray.push(str);
          }
        }

        return strArray.join("");
      },

      toAttendanceDetail: function (attendance, date) {
        var workList = attendance.workdateList;
        if (SysUtil.isEmpty(workList)) {
          return;
        }

        var obj = _.find(workList, {
          workdate: date
        });
        if (obj === undefined) {
          return;
        }

        var postData = {
          userId: attendance.userId,
          date: obj.workdate
        };
        this.loading = true;
        var self = this;
        ajaxRequest('dingTalk/getUserAttendInfo', postData).then(function (attendanceDetail) {
          if (attendanceDetail !== null) {
            var leaveList = attendance.leaveList;
            leaveList = _.filter(leaveList, function (leave) {
              return moment(date).isBetween(leave.startTime, leave.endTime, 'day', '[]');
            });
            attendanceDetail.leaveList = leaveList;
          }
          self.attendanceDetail = attendanceDetail;
          self.detailTitle = `${attendance.userName} ${moment(date).format('YYYY-MM-DD dddd')}`;
          self.openDetail = true;
          self.loading = false;
        }).catch(function () {
          self.loading = false;
        });
      },

      lookSalaryDetail: function (attendance) {
        this.selectAttendance = attendance;
        this.openSalaryDailog = true;
      },

      exportExcel: function () {
        this.search = _.cloneDeep(this.oldSearch);
        var postData = this.getPostData();
        var formParam = SysUtil.formatFormParam(postData);
        var basePath = SysUtil.getBasePath();
        var path = `${basePath}/dingTalk/exportQuerySummaryBody?${formParam}`;
        window.open(path);
      }
    },

    components: {
      SearchBtnView: SearchBtnView,
      SearchForm: AttendanceSearchForm,
      AttendanceDetail: AttendanceDetail,
      SalaryDetail: SalaryDetail
    }
  });

</script>

<style>
  .month-summary {
    padding: 10px 20px;
    padding-bottom: 5px;
    height: calc(100% - 15px);
  }

  .month-summary .month-summary-table-div {
    height: calc(100% - 46px);
    overflow: auto;
  }

  .month-summary .month-summary-table-div.hasPage {
    height: calc(100% - 88px);
  }

  .month-summary .tableHeader {
    display: block;
    height: 20px;
    line-height: 20px;
    font-weight: bold;
  }

  .month-summary .attednanceInfo {
    text-align: center;
  }

  .month-summary .attednanceInfo>div {
    cursor: pointer;
    font-size: 12px;
  }

  .month-summary .attednanceInfo>div.state-0 {
    color: #FF9533;
  }

  .month-summary .attednanceInfo>div.state-1 {
    color: #4B8DFA;
  }

  .month-summary .table-btns {
    color: #409EFF;
    text-align: center;
    cursor: pointer;
  }

  .attendanceDetailDialog .el-dialog__title {
    font-size: 14px;
  }

</style>

</html>
